﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using HotelSoftBusLib;
using HzsClientService.Common;

namespace HzsClientService
{
    public partial class HzsHotelClientService : ServiceBase
    {
        private static readonly string CommonLogPath = ConfigurationManager.AppSettings["LogPath"].ToString();
        static Log log = new Log(CommonLogPath + System.DateTime.Now.ToString("yyyyMMdd") + ".log");
        public HzsHotelClientService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                Thread tServer = new Thread(StartServerListen);
                tServer.Start();
            }
            catch (Exception ex)
            {
                log.WriteLog(ex.Message);
                throw new Exception(ex.Message);
            }
        }

        protected override void OnStop()
        {
        }

        #region  开始监听

        public static void StartServerListen()
        {
            try
            {
                Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Parse(AppGlobal.gLocalIp);
                IPEndPoint iep = new IPEndPoint(ip, AppGlobal.gLocalPort);
                listenSocket.Bind(iep);
                byte[] bytes = new byte[SocketCommdMsg.MAX_BYTE];
                listenSocket.Listen(5);
                while (true)
                {
                    Socket newsocket = listenSocket.Accept();
                    SocketCommdMsg msg = new SocketCommdMsg();
                    SocketReturnMsg rmsg = new SocketReturnMsg();
                    string strReturnMsg = string.Empty;
                    try
                    {
                        int rec = newsocket.Receive(bytes);
                        if (rec > 0)
                        {
                            string strMsg = Encoding.Default.GetString(bytes).TrimEnd('\0');
                            bytes = new byte[SocketCommdMsg.MAX_BYTE];
                            try
                            {
                                msg = Newtonsoft.Json.JsonConvert.DeserializeObject<SocketCommdMsg>(strMsg);
                                rmsg = ExecSocketMsg(msg);
                                strReturnMsg = Newtonsoft.Json.JsonConvert.SerializeObject(rmsg);
                            }
                            catch (Exception ex)
                            {

                                rmsg.IsSuccess = false;
                                rmsg.Status = "-1007";
                                rmsg.Message = "Socket接收字符串格式错误";
                                strReturnMsg = Newtonsoft.Json.JsonConvert.SerializeObject(rmsg);
                                log.WriteLog("Socket接收字符串格式错误");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        rmsg.IsSuccess = false;
                        rmsg.Status = "-1006";
                        rmsg.Message = "Socket数据接收错误" + ex.Message;
                        strReturnMsg = Newtonsoft.Json.JsonConvert.SerializeObject(rmsg);
                        log.WriteLog("Socket数据接收错误" + ex.Message);
                    }
                    byte[] NewByte = new byte[SocketReturnMsg.MAX_BYTE];
                    NewByte = Encoding.Default.GetBytes(strReturnMsg);
                    newsocket.Send(NewByte);
                }
            }
            catch (Exception ex)
            {
                log.WriteLog("服务未开启！" + ex.Message);
                throw new Exception("服务未开启！");
            }
        }
        #endregion

        #region 消息处理
        /// <summary>
        /// 处理接收到的消息，调用对应外部接口函数
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static SocketReturnMsg ExecSocketMsg(SocketCommdMsg msg)
        {
            SocketReturnMsg retMsg = new SocketReturnMsg();
            if (msg == null)
            {
                retMsg.IsSuccess = false;
                retMsg.Message = "接收到信息为空";
                retMsg.Status = "-2";
            }
            else
            {
                try
                {
                    if (msg.MsgType == "CheckIn")
                    {
                        retMsg = CheckIn(msg);
                    }
                    else if (msg.MsgType == "ReadCardData")
                    {
                        retMsg = ReadCardData();
                    }
                    else if (msg.MsgType == "CheckOut")
                    {
                        retMsg = CheckOut(msg);
                    }
                    else if (msg.MsgType == "SendVIPCard")
                    {
                        retMsg = SendVIPCard(msg);
                    }
                    else
                    {
                        retMsg.IsSuccess = false;
                        retMsg.Message = "接收到信息,为实现对应的接口方法";
                        retMsg.Status = "-2";
                    }
                }
                catch (Exception)
                {
                    retMsg.IsSuccess = false;
                    retMsg.Message = "接收到信息,为实现对应的接口方法";
                    retMsg.Status = "-2";
                    log.WriteLog("接收到信息,为实现对应的接口方法");
                }
            }
            return retMsg;
        }

        #endregion

        #region 调用外部接口程序操作

        /// <summary>
        /// 入住
        /// </summary>
        /// <param name="msg">酒馆软件传入字符串对象</param> 
        /// <returns></returns>
        private static SocketReturnMsg CheckIn(SocketCommdMsg msg)
        {
            SocketReturnMsg rmsg = new SocketReturnMsg();
            int retValue = 0;
            try
            {
                int d = OpenDatabase(AppGlobal.UserName, AppGlobal.PassWord);
                if (d != 0)
                {
                    rmsg.IsSuccess = false;
                    rmsg.Status = d.ToString();
                    rmsg.Message = "启用门锁数据库连接失败";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_连接数据库出错";
                return rmsg;
            }
            int cNo = 0;
            try
            {
                retValue = WriteGuestCard2(msg.CustomerInfo.Name, AppGlobal.CardType, msg.RoomInfo.Number, msg.CheckInTime, msg.CheckOutTime, ref cNo);
                if (retValue == -2)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = retValue.ToString();
                    rmsg.Message = "写卡失败";
                    return rmsg;
                }
                else if (retValue == -100)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = retValue.ToString();
                    rmsg.Message = "数据库未连接";
                    return rmsg;
                }
                else if (retValue == -5)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = retValue.ToString();
                    rmsg.Message = "写卡失败，无效的房间号";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                CloseDatabase();
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_写客人卡出错";
                return rmsg;
            }
            CloseDatabase();
            rmsg.IsSuccess = true;
            rmsg.Status = "0";
            rmsg.Message = "{\"CardNumber\":\"" + cNo.ToString() + "\"}";
            return rmsg;
        }

        /// <summary>
        /// 读取卡信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static SocketReturnMsg ReadCardData()
        {
            SocketReturnMsg rmsg = new SocketReturnMsg();
            int retValue = 0;
            try
            {
                int d = OpenDatabase(AppGlobal.UserName, AppGlobal.PassWord);
                if (d != 0)
                {
                    rmsg.IsSuccess = false;
                    rmsg.Status = d.ToString();
                    rmsg.Message = "启用门锁数据库连接失败";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_连接数据库出错";
                return rmsg;
            }
            int cardtype = 0;
            long cardNo = 0;
            byte bt = 0;
            byte[] Guest = new byte[1024];
            byte[] RoomNo = new byte[1024];
            byte[] checkin = new byte[1024];
            byte[] checkout = new byte[1024];
            string geust = "";
            string roomNumber = "";
            string sdate = "";
            string edate = "";
            try
            {
                retValue = ReadCardData2(ref cardtype, ref cardNo, ref bt, Guest, RoomNo, checkin, checkout);
                if (retValue == 0)
                {
                    geust = Encoding.Default.GetString(Guest).TrimEnd('\0');
                    roomNumber = Encoding.Default.GetString(RoomNo).TrimEnd('\0');
                    sdate = Encoding.Default.GetString(checkin).TrimEnd('\0');
                    edate = Encoding.Default.GetString(checkout).TrimEnd('\0');
                }
                else if (retValue == -2)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-2";
                    rmsg.Message = "读卡失败";
                    return rmsg;
                }
                else if (retValue == -100)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-100";
                    rmsg.Message = "数据库连接未打开";
                    return rmsg;
                }
                else
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-1";
                    rmsg.Message = "读取卡信息出错";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                CloseDatabase();
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_读取卡信息出错";
                return rmsg;
            }
            CloseDatabase();
            rmsg.IsSuccess = true;
            rmsg.Status = "0";
            rmsg.Message = "{\"CardNo\":\"" + cardNo + "\",\"CardType\":\"" + cardtype + "\",\"CustomerName\":\"" + geust + "\",\"RoomNo\":\"" + roomNumber + "\",\"CheckInTime\":\"" + sdate + "\",\"CheckOutTime\":\"" + edate + "\"}";
            return rmsg;
        }

        /// <summary>
        /// 退房
        /// </summary>
        /// <param name="customer"></param>
        /// <param name="room"></param>
        /// <returns></returns>
        private static SocketReturnMsg CheckOut(SocketCommdMsg msg)
        {
            SocketReturnMsg rmsg = new SocketReturnMsg();
            int retValue = 0;
            try
            {
                int d = OpenDatabase(AppGlobal.UserName, AppGlobal.PassWord);
                if (d != 0)
                {
                    rmsg.IsSuccess = false;
                    rmsg.Status = d.ToString();
                    rmsg.Message = "启用门锁数据库连接失败";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_连接数据库出错";
                return rmsg;
            }
            try
            {
                retValue = CheckOut(msg.RoomInfo.Number);
                if (retValue == -100)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-100";
                    rmsg.Message = "数据库连接失败";
                    return rmsg;
                }
                else if (retValue == -5)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-5";
                    rmsg.Message = "无效的房间号码";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                CloseDatabase();
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_退房失败";
                return rmsg;
            }
            CloseDatabase();
            rmsg.IsSuccess = true;
            rmsg.Status = "0";
            rmsg.Message = "退房成功";
            return rmsg;
        }

        /// <summary>
        /// 制作VIP卡
        /// </summary>
        /// <param name="customer"></param>
        /// <returns></returns>
        private static SocketReturnMsg SendVIPCard(SocketCommdMsg msg)
        {
            SocketReturnMsg rmsg = new SocketReturnMsg();
            int retValue = 0;
            try
            {
                int d = OpenDatabase(AppGlobal.UserName, AppGlobal.PassWord);
                if (d != 0)
                {
                    rmsg.IsSuccess = false;
                    rmsg.Status = d.ToString();
                    rmsg.Message = "启用门锁数据库连接失败";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                rmsg.IsSuccess = false;
                rmsg.Status = "-1";
                rmsg.Message = "调用外部接口程序_连接数据库出错";
                return rmsg;
            }
            try
            {
                string customerName = (msg.CustomerInfo == null) ? "" : msg.CustomerInfo.Name;
                string endtime = (string.IsNullOrEmpty(msg.CheckOutTime)) ? "" : msg.CheckOutTime;
                retValue = SendVipCard(customerName, msg.RoomInfo.Number, msg.SendCardType, msg.CardNo, msg.CheckInTime, endtime);
                if (retValue == -100)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-100";
                    rmsg.Message = "数据库连接失败";
                    return rmsg;
                }
                else if (retValue == -5)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-5";
                    rmsg.Message = "无效的房间号码";
                    return rmsg;
                }
                else if (retValue == -1)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-1";
                    rmsg.Message = "无效的日期格式";
                    return rmsg;
                }
                else if (retValue == -106)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-106";
                    rmsg.Message = "无效的卡号";
                    return rmsg;
                }
                else if (retValue == -101)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-101";
                    rmsg.Message = "数据库连接失败";
                    return rmsg;
                }
                else if (retValue == -107)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-107";
                    rmsg.Message = "无效的房间号码";
                    return rmsg;
                }
                else if (retValue == -300)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-300";
                    rmsg.Message = "Socket通讯无效";
                    return rmsg;
                }
                else if (retValue == -108)
                {
                    CloseDatabase();
                    rmsg.IsSuccess = false;
                    rmsg.Status = "-108";
                    rmsg.Message = "终端无回应";
                    return rmsg;
                }
            }
            catch (Exception ex)
            {
                CloseDatabase();
                rmsg.IsSuccess = true;
                rmsg.Status = "0";
                rmsg.Message = "Vip客户写卡失败";
            }
            CloseDatabase();
            rmsg.IsSuccess = true;
            rmsg.Status = "0";
            rmsg.Message = "Vip客户写卡成功";
            return rmsg;
        }

        #endregion

        #region  外部程序接口

        /// <summary>
        /// 连接数据库
        /// </summary>
        /// <param name="uName">数据库登录用户</param>
        /// <param name="pwd">登录用户密码</param>
        /// <returns></returns>
        [DllImport("es200801.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int OpenDatabase(string uName, string pwd);

        /// <summary>
        /// 关闭数据库连接
        /// </summary>
        /// <returns></returns>
        [DllImport("es200801.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int CloseDatabase();

        /// <summary>
        /// 写卡信息，客人入住
        /// </summary>
        /// <param name="customerName">客人姓名</param>
        /// <param name="cardType">卡类型</param>
        /// <param name="roomNumber">房间信息</param>
        /// <param name="beginTime">入住时间</param>
        /// <param name="endTime">截止时间</param>
        /// <param name="cardNo">卡号，返回值类型</param>
        /// <returns></returns>
        [DllImport("es200801.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int WriteGuestCard2(string customerName, int cardType, string roomNumber, string beginTime, string endTime, ref int cardNo);

        /// <summary>
        /// 客人退房
        /// </summary>
        /// <param name="roomNumber">房间信息</param>
        /// <returns></returns>
        [DllImport("es200801.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int CheckOut(string roomNumber);

        /// <summary>
        /// 读取卡号信息
        /// </summary>
        /// <param name="cardType">卡类型，返回值</param>
        /// <param name="cardNo">卡号，返回值</param>
        /// <param name="GuestBatchID">批号，返回值</param>
        /// <param name="Guest">客人姓名，返回值</param>
        /// <param name="RoomNo">房间号，返回值</param>
        /// <param name="CheckinTime">入住时间，返回值</param>
        /// <param name="CheckoutTime">截止时间，返回值</param>
        /// <returns></returns>
        [DllImport("es200801.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int ReadCardData2(ref int cardType, ref long cardNo, ref byte GuestBatchID, byte[] Guest, byte[] RoomNo, byte[] CheckinTime, byte[] CheckoutTime);

        /// <summary>
        /// 发送Vip客户信息
        /// </summary>
        /// <param name="customerName">客人姓名</param>
        /// <param name="roomNo">房间号</param>
        /// <param name="sendCardType">卡类型</param>
        /// <param name="pcCardsn">卡号</param>
        /// <param name="pcBeginTime">入住时间</param>
        /// <param name="pcEndTime">截止时间</param>
        /// <returns></returns>
        [DllImport("es200801.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int SendVipCard(string customerName, string roomNo, int sendCardType, string pcCardsn, string pcBeginTime, string pcEndTime);

        #endregion
    }
}
